package com.weather;

import java.net.URL;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activitate in care se parseaza XML-ul si se afiseaza prognoza meteo
 *
 */

public class WeatherForecast extends Activity implements Runnable{

	private String city, date, condition, temp, humidity, wind;
	private int icon;
	private ProgressDialog dialog;
	private ArrayList<ForecastInfo> forecast;

	private Handler handler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
        	  dialog.dismiss();
        	  //in functie de rezultatul parsarii XML-ului, afiseaza informatia obtinuta sau mesaj de eroare
        	  if(msg.what == 0) {
        		  displayWeather();
        	  } else if(msg.what == 1) {
        		  Toast.makeText(WeatherForecast.this, city+" does not exist!", Toast.LENGTH_SHORT).show();
        		  finish();
        	  } else {
        		  Toast.makeText(WeatherForecast.this,"ERROR!", Toast.LENGTH_SHORT).show();
        		  finish();
        	  }
          }
	};
	
	public void onCreate(Bundle savedInstanceState) {
		
        super.onCreate(savedInstanceState);
        //afiseaza un Progress Dialog
        dialog = ProgressDialog.show(WeatherForecast.this, "", "Loading. Please wait...", true);

		forecast = new ArrayList<ForecastInfo>();
        Intent intent = getIntent ();
        city = intent.getStringExtra("city");
        
        //parseaza XML-ul intr-un alt thread
        Thread parser = new Thread(this);
        parser.start();
	}

	//afiseaza conditiile curente
	private void displayWeather() {
		
		  setContentView(R.layout.forecast);
		  TextView fcity = (TextView) findViewById(R.id.f_city);
    	  fcity.setText("Current weather conditions in "+city+":");
    	  TextView fdate = (TextView) findViewById(R.id.date);
    	  fdate.setText(date);
    	  ImageView image = (ImageView) findViewById(R.id.icon);
    	  image.setImageResource(icon);
    	  
    	  TextView cond = (TextView) findViewById(R.id.condition);
    	  cond.setText(condition);
    	  TextView t = (TextView) findViewById(R.id.temp);
    	  t.setText("Temperature : "+temp+"\u2103");
    	  TextView h = (TextView) findViewById(R.id.humidity);
    	  h.setText(humidity);
    	  TextView w = (TextView) findViewById(R.id.wind);
    	  w.setText(wind);
    	  Button button = (Button) findViewById(R.id.fcast);
    	  
    	  //buton pentru selectarea zilei pentru care se doreste aflarea prognozei
    	  button.setText("Extended Forecast");
    	  button.setOnClickListener(new OnClickListener() {
  		    public void onClick(View v) {
  		    	Intent intent = new Intent();
  		    	intent.setClass(WeatherForecast.this, SelectDay.class);
  		    	for(int i=0; i<4; i++)
  		    		intent.putExtra(Character.toString((char) ('0'+i)), forecast.get(i).getDay());
  		    	startActivityForResult(intent, 1);
  		    }
  		});
	}
	
	@Override
	public void onActivityResult (int requestCode, int responseCode, Intent data) {
		if(requestCode == 1) {
			
			//porneste o noua activitate pentru a afisa prognoza pentru ziua selectata
			ForecastInfo info = forecast.get(responseCode);
			Intent intent = new Intent();
			intent.setClass(WeatherForecast.this, ExtendedForecast.class);
			intent.putExtra("info", info);
			intent.putExtra("city", city);
			startActivity(intent);
		}
	}
	
	@Override
	public void run() {
		
		//parsare XML
		NodeList nodeList;
		try {
			URL url = new URL("http://www.google.com/ig/api?weather="+city);
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(new InputSource(url.openStream()));
			doc.getDocumentElement().normalize();
			
			nodeList = doc.getElementsByTagName("forecast_information");
			if(nodeList.getLength() == 0) {
				handler.sendEmptyMessage(1);
				return;
			}
			date = getInfo("forecast_date", nodeList, 0);
			
			nodeList = doc.getElementsByTagName("current_conditions");
			condition = getInfo("condition", nodeList, 0);
			temp = getInfo("temp_c", nodeList, 0);
			humidity = getInfo("humidity", nodeList, 0);
			icon = parseIconName(getInfo("icon", nodeList, 0));
			wind = getInfo("wind_condition", nodeList, 0);
			
			nodeList = doc.getElementsByTagName("forecast_conditions");
			for(int i=0; i<4; i++) {
				forecast.add(new ForecastInfo(writeProperly(getInfo("day_of_week", nodeList, i)),
						getInfo("low", nodeList, i), parseIconName(getInfo("icon", nodeList,i)),
						getInfo("condition", nodeList,i)));
			}
						
		} catch(Throwable t) {
			handler.sendEmptyMessage(2);
			return;
		}
		handler.sendEmptyMessage(0);
	}
	
	//intoarce argumentul "data" din tag-ul tag din intrarea cu indicele index din lista
	private String getInfo(String tag, NodeList nodeList, int index) {
		
		Element elem;
		elem = (Element) (nodeList.item(index));
		elem = (Element) (elem.getElementsByTagName(tag).item(0));
		return elem.getAttribute("data");
	}
	
	//intoarce id-ul unei imagini
	private int parseIconName(String icon) {
		StringTokenizer t = new StringTokenizer(icon, "/.");
		for(int i=0; i<3; i++)
			t.nextToken();
		return StringToRes(t.nextToken());
	}
	
	public static int StringToRes (String icon) {
		if(icon.equalsIgnoreCase("chance_of_rain"))
			return R.drawable.chance_of_rain;
		if(icon.equalsIgnoreCase("chance_of_snow"))
			return R.drawable.chance_of_snow;
		if(icon.equalsIgnoreCase("chance_of_storm"))
			return R.drawable.chance_of_storm;
		if(icon.equalsIgnoreCase("chance_of_tstorm"))
			return R.drawable.chance_of_tstorm;
		if(icon.equalsIgnoreCase("cloudy"))
			return R.drawable.cloudy;
		if(icon.equalsIgnoreCase("dust"))
			return R.drawable.dust;
		if(icon.equalsIgnoreCase("flurries"))
			return R.drawable.flurries;
		if(icon.equalsIgnoreCase("fog"))
			return R.drawable.fog;
		if(icon.equalsIgnoreCase("haze"))
			return R.drawable.haze;
		if(icon.equalsIgnoreCase("icy"))
			return R.drawable.icy;
		if(icon.equalsIgnoreCase("mist"))
			return R.drawable.mist;
		if(icon.equalsIgnoreCase("mostly_cloudy"))
			return R.drawable.mostly_cloudy;
		if(icon.equalsIgnoreCase("mostly_sunny"))
			return R.drawable.mostly_sunny;
		if(icon.equalsIgnoreCase("partly_cloudy"))
			return R.drawable.partly_cloudy;
		if(icon.equalsIgnoreCase("rain")) 
			return R.drawable.rain;
		if(icon.equalsIgnoreCase("sleet")) 
			return R.drawable.sleet;
		if(icon.equalsIgnoreCase("smoke")) 
			return R.drawable.smoke;
		if(icon.equalsIgnoreCase("snow")) 
			return R.drawable.snow;
		if(icon.equalsIgnoreCase("storm")) 
			return R.drawable.storm;
		if(icon.equalsIgnoreCase("sunny")) 
			return R.drawable.sunny;
		if(icon.equalsIgnoreCase("thunderstorm")) 
			return R.drawable.thunderstorm;
		return 0;
	}

	//functie folosita pentru a se putea afisa ziua saptamanii (ex: "Monday" in loc de "Mon")
	private String writeProperly(String day) {
		
		switch(day.charAt(0)) {
		case 'M':
			return "Monday";
		case 'T':
			if(day.charAt(1) == 'u')
				return "Tuesday";
			return "Thursday";
		case 'W' :
			return "Wednesday";
		case 'F' :
			return "Friday";
		case 'S' :
			if(day.charAt(1) == 'a')
				return "Saturday";
			return "Sunday";
		}
		return null;
	}
}
